﻿using BehaviorModel.Block;
using BehaviorModel.Block.RandomGenerator;
using BehaviorModel.Block.ServiceChannel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace BehaviorModel.XmlSerializer
{
    /// <summary>
    /// Class for Xml Serialization of ServiceChannel Block
    /// </summary>
    class ServiceChannelXmlSerializer : IXmlSerializer
    {
        /// <summary>
        /// Serializes Service Channel to XElement
        /// </summary>
        /// <returns></returns>
        public XElement ToXElement(IBlock block)
        {
            if (block is ServiceChannel)
            {
                ServiceChannel serviceChannel = (ServiceChannel)block;
                XElement serviceGeneratorElement;
                using (var memoryStream = new MemoryStream())
                {
                    using (TextWriter streamWriter = new StreamWriter(memoryStream))
                    {
                        Type type = serviceChannel.ServiceGenerator.GetType();
                        var xmlSerializer = new System.Xml.Serialization.XmlSerializer(serviceChannel.ServiceGenerator.GetType());
                        xmlSerializer.Serialize(streamWriter, serviceChannel.ServiceGenerator);
                        serviceGeneratorElement = XElement.Parse(Encoding.ASCII.GetString(memoryStream.ToArray()));
                    }
                }

                return new XElement(XmlSerializationConstants.SERVICE_CHANNEL_BLOCK,
                    new XElement(XmlSerializationConstants.IS_BUSY, serviceChannel.IsBusy),
                    new XElement(XmlSerializationConstants.SERVICE_CHANNEL_TYPE, serviceChannel.ChannelType),
                    new XElement(XmlSerializationConstants.MAX_QUEUE_LENGTH, serviceChannel.MaxQueueLength),
                    new XElement(XmlSerializationConstants.DISCIPLINE, serviceChannel.Discipline),
                    serviceGeneratorElement,
                    new XElement(XmlSerializationConstants.GENERATOR_TYPE, serviceChannel.GeneratorType));
            }
            else
            {
                throw new ArgumentException();
            }

        }

        /// <summary>
        /// Deserializes XElement to ServiceChannel
        /// </summary>
        /// <param name="xElement"></param>
        /// <returns></returns>
        public IBlock FromXElement(XElement xElement)
        {
            ServiceChannel serviceChannel = new ServiceChannel();
            serviceChannel.IsBusy = Boolean.Parse(xElement.Element(XmlSerializationConstants.SERVICE_CHANNEL_BLOCK).Element(XmlSerializationConstants.IS_BUSY).Value);
            serviceChannel.ChannelType = (ServiceChannelType)Enum.Parse(typeof(ServiceChannelType), xElement.Element(XmlSerializationConstants.SERVICE_CHANNEL_BLOCK).Element(XmlSerializationConstants.SERVICE_CHANNEL_TYPE).Value);
            serviceChannel.MaxQueueLength = Int32.Parse(xElement.Element(XmlSerializationConstants.SERVICE_CHANNEL_BLOCK).Element(XmlSerializationConstants.MAX_QUEUE_LENGTH).Value);
            serviceChannel.Discipline = (ChoosingDiscipline)Enum.Parse(typeof(ChoosingDiscipline), xElement.Element(XmlSerializationConstants.SERVICE_CHANNEL_BLOCK).Element(XmlSerializationConstants.DISCIPLINE).Value);
            serviceChannel.GeneratorType = (RandomGeneratorType)Enum.Parse(typeof(RandomGeneratorType), xElement.Element(XmlSerializationConstants.SERVICE_CHANNEL_BLOCK).Element(XmlSerializationConstants.GENERATOR_TYPE).Value);
            IRandomGenerator serviceGenerator;
            using (var memoryStream = new MemoryStream(Encoding.ASCII.GetBytes(xElement.Element(XmlSerializationConstants.SERVICE_CHANNEL_BLOCK).Element(serviceChannel.GeneratorType.ToString() + "RandomGenerator").ToString())))
            {
                var xmlSerializer = new System.Xml.Serialization.XmlSerializer(Type.GetType("BehaviorModel.Block.RandomGenerator." + serviceChannel.GeneratorType.ToString() + "RandomGenerator"));
                serviceGenerator = (IRandomGenerator)xmlSerializer.Deserialize(memoryStream);
            };
            serviceChannel.ServiceGenerator = serviceGenerator;
            return serviceChannel;
        }
    }
}
